package com.tmt.im.wallet.service;

import com.tmt.data.jpa.service.TmtJpaDataService;
import com.tmt.im.common.enums.ChannelType;
import com.tmt.im.jpa.entity.IMUser;
import com.tmt.im.jpa.entity.SystemParam;
import com.tmt.im.jpa.entity.WithdrawBindingParam;
import com.tmt.im.jpa.repository.IMUserRepo;
import com.tmt.im.jpa.repository.WithdrawBindingParamRepo;
import com.tmt.im.wallet.config.beans.CurrentServiceProperties;
import com.tmt.im.wallet.controler.vo.WithdrawParamBindingRequest;
import com.tmt.im.wallet.controler.vo.WithdrawParamItem;
import com.tmt.springboot.common.helper.IdSnowFlake;
import com.tmt.springboot.common.restful.ExecuteResult;
import com.tmt.springboot.common.restful.IExecuteResult;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.http.Method;
import org.apache.commons.lang3.mutable.MutableFloat;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.security.Principal;
import java.sql.Timestamp;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @Description TODO
 * @Author wuyi
 * @Date 2024/10/20 14:07
 * @Version 1.0
 **/
@Service
public class WithdrawBindingParamService extends TmtJpaDataService<WithdrawBindingParam, Long> {

    private final String bucket;

    private final String qrCodeUrlTemplate;

    private final CurrentServiceProperties serviceProperties;

    private final WithdrawBindingParamRepo bindingParamRepo;

    private final IMUserRepo imUserRepo;

    private final MinioClient minioClient;

    public WithdrawBindingParamService(@Value("${minio.bucket}")
                                       String bucket,
                                       @Value("${qr-code-url-template}")
                                       String qrCodeUrlTemplate,
                                       CurrentServiceProperties serviceProperties,
                                       WithdrawBindingParamRepo mainRepo,
                                       IMUserRepo imUserRepo,
                                       MinioClient minioClient) {
        super(mainRepo);
        this.bucket = bucket;
        this.qrCodeUrlTemplate = qrCodeUrlTemplate;
        this.serviceProperties = serviceProperties;
        this.bindingParamRepo = mainRepo;
        this.imUserRepo = imUserRepo;
        this.minioClient = minioClient;
    }

    public IExecuteResult<String> bindingWithdrawParams(Long currentUserId, WithdrawParamBindingRequest request, Principal principal) {
        ChannelType channelType = request.getChannelType();
        if (channelType == ChannelType.ALI_PAY) {
            if (!StringUtils.hasText(request.getBankCardAccount())) {
                return ExecuteResult.failure("bankCardAccount参数不能为空，应赋值为支付宝账号", null);
            }
            if (!StringUtils.hasText(request.getAccountHolder())) {
                return ExecuteResult.failure("accountHolder参数不能为空，应赋值为支付宝收款人(真实姓名)", null);
            }
        } else if (channelType == ChannelType.WE_CHAT) {
            if (!StringUtils.hasText(request.getAccountHolder())) {
                return ExecuteResult.failure("accountHolder参数不能为空，应赋值为微信收款人昵称", null);
            }
            if (request.getFileData().isEmpty()) {
                return ExecuteResult.failure("fileData参数不能为空，应赋值为微信的收款二维码文件数据", null);
            }
        } else {
            if (!StringUtils.hasText(request.getBankCardAccount())) {
                return ExecuteResult.failure("bankCardAccount参数不能为空，应赋值为银行卡号", null);
            }
            if (!StringUtils.hasText(request.getOpenAccountBank())) {
                return ExecuteResult.failure("openAccountBank参数不能为空，应赋值为开户行信息", null);
            }
            if (!StringUtils.hasText(request.getAccountHolder())) {
                return ExecuteResult.failure("accountHolder参数不能为空，应赋值为开户人姓名", null);
            }
        }

        WithdrawBindingParam param = bindingParamRepo.findOneByCreatorIdAndChannelType(currentUserId, channelType.name());
        if (param == null) {
            param = new WithdrawBindingParam();
            param.setId(IdSnowFlake.getId());
            param.setChannelType(channelType.name());
            param.setVersion(0L);

            IMUser user = imUserRepo.findById(currentUserId).orElse(null);
            assert user != null;
            param.setCreator(user);
        }

        if (channelType == ChannelType.ALI_PAY) {
            param.setBankCardAccount(request.getBankCardAccount());
            param.setOpenAccountBank(null);
            param.setAccountHolder(request.getAccountHolder());
        } else if (channelType == ChannelType.WE_CHAT) {
            param.setBankCardAccount(null);
            param.setOpenAccountBank(null);
            param.setAccountHolder(request.getAccountHolder());
            try {
                if (!request.getFileData().isEmpty()) {
                    IExecuteResult<String> executeResult = saveFileToOSS(param.getId(), request.getFileData());
                    if (executeResult.getCode() != ExecuteResult.SUCCESS_CODE){
                        return executeResult;
                    }
                    param.setFileUri(executeResult.getData());
                }
            } catch (Exception ex) {
                return ExecuteResult.failure("读取fileData参数失败：" + ex.getMessage(), null);
            }
        } else {
            param.setBankCardAccount(request.getBankCardAccount());
            param.setOpenAccountBank(request.getOpenAccountBank());
            param.setAccountHolder(request.getAccountHolder());
        }
        param.setCreateTime(new Timestamp(System.currentTimeMillis()));
        bindingParamRepo.save(param);

        String url = null;
        if (StringUtils.hasText(param.getFileUri())) {
            url = "http://" + serviceProperties.getExternalClientService() + param.getFileUri();
        }
        return ExecuteResult.success("操作成功", url);
    }

    public IExecuteResult<Boolean> deleteWithdrawParam(Long currentUserId, ChannelType channelType, Principal principal) {
        WithdrawBindingParam param = bindingParamRepo.findOneByCreatorIdAndChannelType(currentUserId, channelType.name());
        if (param != null) {
            bindingParamRepo.delete(param);
            return ExecuteResult.success(true);
        }
        return ExecuteResult.failure("目标参数记录不存在", false);
    }

    public IExecuteResult<List<WithdrawParamItem>> queryWithdrawParams(Long currentUserId, Principal principal) {
        List<WithdrawParamItem> items = new ArrayList<>();
        List<WithdrawBindingParam> params = bindingParamRepo.findAllByCreatorId(currentUserId);
        for (WithdrawBindingParam param : params) {
            WithdrawParamItem item = new WithdrawParamItem();
            items.add(item);
            BeanUtils.copyProperties(param, item);
            String url = "http://" + serviceProperties.getExternalClientService() + param.getFileUri();
            item.setFileUrl(url);
        }
        return ExecuteResult.success(items);
    }

    private IExecuteResult<String> saveFileToOSS(Long fileId, MultipartFile fileData){
        try {
            String fileName = fileData.getOriginalFilename();
            assert fileName != null;

            //获取文件扩展名称。
            int index = fileName.lastIndexOf(".");
            String ext = index > 0 && index + 1 < fileName.length() ? fileName.substring(index) : "";
            //文件名称。
            fileName = MessageFormat.format("file/{0}{1}", "" + fileId, ext);

            //确定ContentType参数
            String contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
            if (ext.toLowerCase().endsWith("png")) {
                contentType = MediaType.IMAGE_PNG_VALUE;
            } else if (ext.toLowerCase().endsWith("jpg")) {
                contentType = MediaType.IMAGE_JPEG_VALUE;
            } else if (ext.toLowerCase().endsWith("gif")) {
                contentType = MediaType.IMAGE_GIF_VALUE;
            }

            //将文件保存到minio中。
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(this.bucket)      // 指定 Bucket
                    .contentType(contentType)// 指定 Content Type
                    .object(fileName)        // 指定文件的路径
                    .stream(fileData.getInputStream(), fileData.getSize(), -1) // 文件的 Inputstream 流
                    .build());

            String url = MessageFormat.format(qrCodeUrlTemplate, "" + fileId + ext);
            return ExecuteResult.success("操作成功", url);
        }catch (Exception ex){
            return ExecuteResult.failure(ex.getMessage(), null);
        }
    }

}
